home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / dflat_r_.arc / EDITBOX.C < prev    next >
Text File  |  1991-10-02  |  32KB  |  1,293 lines

  1. /* ------------- editbox.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <ctype.h>
  8. #include "dflat.h"
  9.  
  10. #define EDITBUFFERLENGTH  4096
  11. #define ENTRYBUFFERLENGTH 1024
  12. #define GROWLENGTH        1024
  13.  
  14.  
  15. #define EditBufLen(wnd) (isMultiLine(wnd) ? EDITBUFFERLENGTH : ENTRYBUFFERLENGTH)
  16. #define WndCol (wnd->CurrCol-wnd->wleft)
  17.  
  18. #define CurrChar (TextLine(wnd, wnd->CurrLine)+wnd->CurrCol)
  19.  
  20. static void PasteText(WINDOW, char *, int);
  21. static void SaveDeletedText(WINDOW, char *, int);
  22. static void Forward(WINDOW);
  23. static void Backward(WINDOW);
  24. static void End(WINDOW);
  25. static void Home(WINDOW);
  26. static void Downward(WINDOW);
  27. static void Upward(WINDOW);
  28. static void StickEnd(WINDOW);
  29. static void UpLine(WINDOW);
  30. static void DownLine(WINDOW);
  31. static void NextWord(WINDOW);
  32. static void PrevWord(WINDOW);
  33. static void ResetEditBox(WINDOW);
  34. static void AddTextPointers(WINDOW, int, int);
  35. static int TextLineNumber(WINDOW, char *);
  36. #ifdef INCLUDE_DIALOG_BOXES
  37. static void SearchTextBox(WINDOW);
  38. static void ReplaceTextBox(WINDOW);
  39. static void SearchNext(WINDOW, int);
  40. #endif
  41. #ifdef INCLUDE_MULTILINE
  42. #define SetLinePointer(wnd, ln)    (wnd->CurrLine = ln)
  43. #else
  44. #define SetLinePointer(wnd, ln) (wnd->CurrLine = 0)
  45. #endif
  46.  
  47. static int KeyBoardMarking, ButtonDown;
  48. int TextMarking;
  49. static int bx, by;
  50.  
  51. char *Clipboard;
  52. int ClipboardLength;
  53.  
  54. int EditBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  55. {
  56.     int rtn;
  57.     static int py = -1;
  58.     int kx = (int) p1 - GetLeft(wnd);
  59.     int ky = (int) p2 - GetTop(wnd);
  60.     int c;
  61.     RECT rc;
  62.     char *lp;
  63.     int len;
  64.     int    mx;
  65.     int    my;
  66.     char *currchar = CurrChar;
  67.     int PassOn = FALSE;
  68.  
  69.     rc = ClientRect(wnd);
  70.     switch (msg)    {
  71.         case CREATE_WINDOW:
  72.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  73.             wnd->text = calloc(1, EditBufLen(wnd)+1);
  74.             wnd->textlen = EditBufLen(wnd);
  75.             ResetEditBox(wnd);
  76.             return rtn;
  77.         case ADDTEXT:
  78.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  79.             currchar = CurrChar;
  80.             if (!isMultiLine(wnd))    {
  81.                 wnd->CurrLine = 0;
  82.                 wnd->CurrCol = strlen((char *)p1);
  83.                 if (wnd->CurrCol >= ClientWidth(wnd))    {
  84.                     wnd->wleft = wnd->CurrCol - ClientWidth(wnd);
  85.                     wnd->CurrCol -= wnd->wleft;
  86.                 }
  87.                 wnd->BlkEndCol = wnd->CurrCol;
  88.                 PostMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  89.             }
  90.             BuildTextPointers(wnd);
  91.             return rtn;
  92.         case SETTEXT:
  93.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  94.             wnd->CurrLine = 0;
  95.             return rtn;
  96.         case CLEARTEXT:
  97.             ResetEditBox(wnd);
  98.             ClearTextPointers(wnd);
  99.             break;
  100.         case KEYBOARD_CURSOR:
  101.             wnd->CurrCol = (int)p1 + wnd->wleft;
  102.             wnd->WndRow = (int)p2;
  103.             wnd->CurrLine = (int)p2 + wnd->wtop;
  104.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  105.             if (wnd == inFocus)    {
  106.                 if (!CharInView(wnd, (int)p1+BorderAdj(wnd),
  107.                         (int)p2+TopBorderAdj(wnd)))
  108.                     SendMessage(NULLWND, HIDE_CURSOR, 0, 0);
  109.                 else 
  110.                     SendMessage(NULLWND, SHOW_CURSOR,
  111.                         GetCommandToggle(&MainMenu, ID_INSERT), 0);
  112.             }
  113.             return rtn;
  114.         case EB_GETTEXT:    {
  115.             char *cp1 = (char *)p1;
  116.             char *cp2 = wnd->text;
  117.             while (p2-- && *cp2 && *cp2 != '\n')
  118.                 *cp1++ = *cp2++;
  119.             *cp1 = '\0';
  120.             return TRUE;
  121.         }
  122.         case EB_PUTTEXT:
  123.             SendMessage(wnd, CLEARTEXT, 0, 0);
  124.             SendMessage(wnd, ADDTEXT, p1, p2);
  125.             return TRUE;
  126.         case SETFOCUS:
  127.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  128.             if (p1)    {
  129.                 SendMessage(NULLWND, SHOW_CURSOR, GetCommandToggle(&MainMenu, ID_INSERT), 0);
  130.                 SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  131.             }
  132.             else
  133.                 SendMessage(NULLWND, HIDE_CURSOR, 0, 0);
  134.             return rtn;
  135. #ifdef INCLUDE_MULTILINE
  136.         case SHIFT_CHANGED:
  137.             if (!((int)p1 & (LEFTSHIFT | RIGHTSHIFT)) && KeyBoardMarking)    {
  138.                 SendMessage(wnd, BUTTON_RELEASED, 0, 0);
  139.                 KeyBoardMarking = FALSE;
  140.             }
  141.             break;
  142.         case DOUBLE_CLICK:
  143.             if (KeyBoardMarking)
  144.                 return TRUE;
  145.             break;
  146. #endif
  147.         case LEFT_BUTTON:
  148. #ifdef INCLUDE_MULTILINE
  149.             if (KeyBoardMarking || TextMarking)
  150.                 return TRUE;
  151. #endif
  152. #ifdef INCLUDE_SYSTEM_MENUS
  153.             if (WindowMoving || WindowSizing)
  154.                 break;
  155. #endif
  156.             if (!InsideRect(p1, p2, rc))
  157.                 break;
  158.  
  159.             mx = (int) p1 - GetClientLeft(wnd);
  160.             my = (int) p2 - GetClientTop(wnd);
  161.  
  162. #ifdef INCLUDE_MULTILINE
  163.             if (isMultiLine(wnd))    {
  164.  
  165.                 if (BlockMarked(wnd))    {
  166.                     ClearBlock(wnd);
  167.                     SendMessage(wnd, PAINT, 0, 0);
  168.                 }
  169.  
  170.                 if (wnd->wlines)    {
  171.                     if (my > wnd->wlines-1)
  172.                         break;
  173.                     lp = TextLine(wnd, my+wnd->wtop);
  174.                     len = (int) (strchr(lp, '\n') - lp);
  175.                     mx = min(mx, len);
  176.                     if (mx < wnd->wleft)    {
  177.                         mx = 0;
  178.                         SendMessage(wnd, KEYBOARD, HOME, 0);
  179.                     }
  180.                     ButtonDown = TRUE;
  181.                     bx = mx;
  182.                     by = my;
  183.                 }
  184.                 else
  185.                     mx = my = 0;
  186.  
  187.                 wnd->WndRow = my;
  188.                 SetLinePointer(wnd, my+wnd->wtop);
  189.             }
  190. #endif
  191.             if (isMultiLine(wnd) ||
  192.                 (!BlockMarked(wnd)
  193.                     && mx+wnd->wleft < strlen(wnd->text)))
  194.                 wnd->CurrCol = mx+wnd->wleft;
  195.             PostMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  196.             return TRUE;
  197. #ifdef INCLUDE_MULTILINE
  198.         case MOUSE_MOVED:
  199.             mx = (int) p1 - GetClientLeft(wnd);
  200.             my = (int) p2 - GetClientTop(wnd);
  201.             if (my > wnd->wlines-1)
  202.                 break;
  203.  
  204.             if (ButtonDown)    {
  205.                 SetAnchor(wnd, bx+wnd->wleft, by+wnd->wtop);
  206.                 TextMarking = TRUE;
  207.                 SendMessage(wnd, CAPTURE_MOUSE, TRUE, 0);
  208.                 ButtonDown = FALSE;
  209.             }
  210.  
  211.             if (TextMarking
  212. #ifdef INCLUDE_SYSTEM_MENUS
  213.                     && !(WindowMoving || WindowSizing)
  214. #endif
  215.                             )    {
  216.                 int ptop;
  217.                 int pbot;
  218.                 char *lp;
  219.                 int len;
  220.                 int y;
  221.                 int bbl, bel;
  222.                 RECT rc;
  223.                 rc = ClientRect(wnd);
  224.  
  225.                 if (!InsideRect(p1, p2, rc))      {
  226.                     int hs = -1, sc = -1;
  227.                     if (p1 < GetClientLeft(wnd))    {
  228.                         hs = FALSE;
  229.                         p1 = GetClientLeft(wnd);
  230.                     }
  231.                     if (p1 > GetClientRight(wnd))    {
  232.                         hs = TRUE;
  233.                         p1 = GetClientRight(wnd);
  234.                     }
  235.                     if (p2 < GetClientTop(wnd))    {
  236.                         sc = FALSE;
  237.                         p2 = GetClientTop(wnd);
  238.                     }
  239.                     if (p2 > GetClientBottom(wnd))    {
  240.                         sc = TRUE;
  241.                         p2 = GetClientBottom(wnd);
  242.                     }
  243.                     SendMessage(NULLWND, MOUSE_CURSOR, p1, p2);
  244.                     if (sc != -1)
  245.                         SendMessage(wnd, SCROLL, sc, 0);
  246.                     if (hs != -1)
  247.                         SendMessage(wnd, HORIZSCROLL, hs, 0);
  248.                     mx = (int) p1 - GetClientLeft(wnd);
  249.                     my = (int) p2 - GetClientTop(wnd);
  250.                 }
  251.  
  252.                 ptop = min(wnd->BlkBegLine, wnd->BlkEndLine);
  253.                 pbot = max(wnd->BlkBegLine, wnd->BlkEndLine);
  254.  
  255.                 lp = TextLine(wnd, wnd->wtop+my);
  256.                 len = (int) (strchr(lp, '\n') - lp);
  257.                 mx = min(mx, len-wnd->wleft);
  258.  
  259.                 wnd->BlkEndCol = mx+wnd->wleft;
  260.                 wnd->BlkEndLine = my+wnd->wtop;
  261.  
  262.                 bbl = min(wnd->BlkBegLine, wnd->BlkEndLine);
  263.                 bel = max(wnd->BlkBegLine, wnd->BlkEndLine);
  264.  
  265.                 while (ptop < bbl)    {
  266.                     WriteTextLine(wnd, NULL, ptop, FALSE);
  267.                     ptop++;
  268.                 }
  269.                 for (y = bbl; y <= bel; y++)
  270.                     WriteTextLine(wnd, NULL, y, FALSE);
  271.                 while (pbot > bel)    {
  272.                     WriteTextLine(wnd, NULL, pbot, FALSE);
  273.                     --pbot;
  274.                 }
  275.                 return TRUE;
  276.             }
  277.             break;
  278.         case BUTTON_RELEASED:
  279.             if (!isMultiLine(wnd))
  280.                 break;
  281.             ButtonDown = FALSE;
  282.             if (TextMarking
  283. #ifdef INCLUDE_SYSTEM_MENUS
  284.                     && !(WindowMoving || WindowSizing)
  285. #endif
  286.                             )    {
  287.                 PostMessage(wnd, RELEASE_MOUSE, 0, 0);
  288.                 TextMarking = FALSE;
  289.                 if (wnd->BlkBegLine > wnd->BlkEndLine)    {
  290.                     swap(wnd->BlkBegLine, wnd->BlkEndLine);
  291.                     swap(wnd->BlkBegCol, wnd->BlkEndCol);
  292.                 }
  293.                 if (wnd->BlkBegLine == wnd->BlkEndLine &&
  294.                         wnd->BlkBegCol > wnd->BlkEndCol)
  295.                     swap(wnd->BlkBegCol, wnd->BlkEndCol);
  296.                 return TRUE;
  297.             }
  298.             else
  299.                 py = -1;
  300.             break;
  301.         case PAINT:
  302.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  303.             if (isVisible(wnd))
  304.                 SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  305.             return rtn;
  306.         case SCROLL:
  307.             if (!isMultiLine(wnd))
  308.                 break;
  309.             if ((rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2)) != FALSE)    {
  310.                 if (p1)    {
  311.                     /* -------- scrolling up --------- */
  312.                     if (wnd->WndRow == 0)    {
  313.                         DownLine(wnd);
  314.                         StickEnd(wnd);
  315.                     }
  316.                     else
  317.                         --wnd->WndRow;
  318.                 }
  319.                 else    {
  320.                     /* -------- scrolling down --------- */
  321.                     if (wnd->WndRow == ClientHeight(wnd)-1)    {
  322.                         UpLine(wnd);
  323.                         StickEnd(wnd);
  324.                     }
  325.                     else
  326.                         wnd->WndRow++;
  327.                 }
  328.                 if (!(int)p2)
  329.                     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  330.             }
  331.             return rtn;
  332. #endif
  333.         case HORIZSCROLL:
  334.             if (p1 && wnd->CurrCol == wnd->wleft &&
  335.                     *currchar == '\n')
  336.                 return FALSE;
  337.             if ((rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2)) != FALSE)    {
  338.                 if (wnd->CurrCol < wnd->wleft)
  339.                     wnd->CurrCol++;
  340.                 else if (WndCol == ClientWidth(wnd))
  341.                     --wnd->CurrCol;
  342.                 SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  343.             }
  344.             return rtn;
  345. #ifdef INCLUDE_SYSTEM_MENUS
  346.         case MOVE:
  347.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  348.             SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  349.             return rtn;
  350.         case SIZE:
  351.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  352.             if (WndCol > ClientWidth(wnd)-1)
  353.                 wnd->CurrCol = ClientWidth(wnd)-1 + wnd->wleft;
  354.             if (wnd->WndRow > ClientHeight(wnd)-1)    {
  355.                 wnd->WndRow = ClientHeight(wnd)-1;
  356.                 SetLinePointer(wnd, wnd->WndRow+wnd->wtop);
  357.             }
  358.             SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  359.             return rtn;
  360. #endif
  361.         case KEYBOARD:
  362. #ifdef INCLUDE_SYSTEM_MENUS
  363.             if (WindowMoving || WindowSizing)
  364.                 break;
  365. #endif
  366.             if ((int)p2 & ALTKEY)
  367.                 break;
  368.             c = (int) p1;
  369.             switch (c)    {
  370.                 case CTRL_FWD:
  371.                 case CTRL_BS:
  372.                 case CTRL_HOME:
  373.                 case CTRL_END:
  374.                 case CTRL_PGUP:
  375.                 case CTRL_PGDN:
  376.                     break;
  377.                 case ESC:
  378.                 case F1:
  379.                 case F2:
  380.                 case F3:
  381.                 case F4:
  382.                 case F5:
  383.                 case F6:
  384.                 case F7:
  385.                 case F8:
  386.                 case F9:
  387.                 case F10:
  388.                 case SHIFT_INS:
  389.                 case SHIFT_DEL:
  390.                     PassOn = TRUE;
  391.                 default:
  392.                     if ((int)p2 & CTRLKEY)
  393.                         PassOn = TRUE;
  394.                 break;
  395.             }
  396.             if (PassOn)
  397.                 break;
  398. #ifdef INCLUDE_MULTILINE
  399.             if (isMultiLine(wnd))    {
  400.                 if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT))    {
  401.                     SendMessage(NULLWND, CURRENT_KEYBOARD_CURSOR,
  402.                         (PARAM) &kx, (PARAM) &ky);
  403.  
  404.                     kx -= GetClientLeft(wnd);
  405.                     ky -= GetClientTop(wnd);
  406.  
  407.                     switch (c)    {
  408.                         case HOME:
  409.                         case END:
  410.                         case PGUP:
  411.                         case PGDN:
  412.                         case CTRL_PGUP:
  413.                         case CTRL_PGDN:
  414.                         case UP:
  415.                         case DN:
  416.                         case FWD:
  417.                         case BS:
  418.                         case CTRL_FWD:
  419.                         case CTRL_BS:
  420.                             if (!KeyBoardMarking)    {
  421.                                 if (BlockMarked(wnd))    {
  422.                                     ClearBlock(wnd);
  423.                                     SendMessage(wnd, PAINT, 0, 0);
  424.                                 }
  425.                                 KeyBoardMarking = TextMarking = TRUE;
  426.                                 SetAnchor(wnd, kx+wnd->wleft, ky+wnd->wtop);
  427.                             }
  428.                             break;
  429.                         default:
  430.                             break;
  431.                     }
  432.                 }
  433.                 else if (((c != DEL && c != RUBOUT) ||
  434.                         !isMultiLine(wnd)) && BlockMarked(wnd))    {
  435.                     ClearBlock(wnd);
  436.                     SendMessage(wnd, PAINT, 0, 0);
  437.                 }
  438.             }
  439. #endif
  440.             switch (c)    {
  441. #ifdef INCLUDE_MULTILINE
  442.                 case PGUP:
  443.                 case PGDN:
  444.                     if (!isMultiLine(wnd))
  445.                         break;
  446.                     BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  447.                     SetLinePointer(wnd, wnd->wtop+wnd->WndRow);
  448.                     StickEnd(wnd);
  449.                     SendMessage(wnd, KEYBOARD_CURSOR,WndCol, wnd->WndRow);
  450.                     break;
  451. #endif
  452.                 case HOME:
  453.                     Home(wnd);
  454.                     break;
  455.                 case END:
  456.                     End(wnd);
  457.                     break;
  458.                 case CTRL_FWD:
  459.                     NextWord(wnd);
  460.                     break;
  461.                 case CTRL_BS:
  462.                     PrevWord(wnd);
  463.                     break;
  464.                 case CTRL_HOME:
  465.                     if (!isMultiLine(wnd))    {
  466.                         Home(wnd);
  467.                         break;
  468.                     }
  469. #ifdef INCLUDE_MULTILINE
  470.                     rtn = BaseWndProc(EDITBOX, wnd, msg, HOME, p2);
  471.                     Home(wnd);
  472.                     wnd->CurrLine = 0;
  473.                     wnd->WndRow = 0;
  474.                     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  475.                     return rtn;
  476. #endif
  477.                 case CTRL_END:
  478.                     if (!isMultiLine(wnd))    {
  479.                         End(wnd);
  480.                         break;
  481.                     }
  482. #ifdef INCLUDE_MULTILINE
  483.                     Home(wnd);
  484.                     rtn = BaseWndProc(EDITBOX, wnd, msg, END, p2);
  485.                     if (wnd->wlines > 0)    {
  486.                         SetLinePointer(wnd, wnd->wlines-1);
  487.                         wnd->WndRow = min(ClientHeight(wnd)-1, wnd->wlines-1);
  488.                     }
  489.                     End(wnd);
  490.                     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  491.                     return rtn;
  492. #endif
  493. #ifdef INCLUDE_MULTILINE
  494.                 case UP:
  495.                     if (!isMultiLine(wnd))
  496.                         break;
  497.                     Upward(wnd);
  498.                     break;
  499.                 case DN:
  500.                     if (!isMultiLine(wnd))
  501.                         break;
  502.                     Downward(wnd);
  503.                     break;
  504. #endif
  505.                 case FWD:
  506.                     Forward(wnd);
  507.                     break;
  508.                 case BS:
  509.                     Backward(wnd);
  510.                     break;
  511.                 case CTRL_PGUP:
  512.                     BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  513.                     if (wnd->CurrCol > wnd->wleft+ClientWidth(wnd)-1)
  514.                         wnd->CurrCol = wnd->wleft+ClientWidth(wnd)-1;
  515.                     SendMessage(wnd, KEYBOARD_CURSOR,WndCol, wnd->WndRow);
  516.                     break;
  517.                 case CTRL_PGDN:
  518.                     BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  519.                     if (wnd->CurrCol < wnd->wleft)
  520.                         wnd->CurrCol = wnd->wleft;
  521.                     SendMessage(wnd, KEYBOARD_CURSOR,WndCol, wnd->WndRow);
  522.                     break;
  523.                 default:
  524.                     break;
  525.             }
  526. #ifdef INCLUDE_MULTILINE
  527.             if (KeyBoardMarking)    {
  528.                 SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  529.                 SendMessage(NULLWND, CURRENT_KEYBOARD_CURSOR,
  530.                     (PARAM) &kx, (PARAM) &ky);
  531.                 SendMessage(wnd, MOUSE_MOVED, kx, ky);
  532.                 return TRUE;
  533.             }
  534. #endif
  535.             if (!TestAttribute(wnd, READONLY))    {
  536.                 switch (c)    {
  537.                     case HOME:
  538.                     case END:
  539.                     case PGUP:
  540.                     case PGDN:
  541.                     case CTRL_PGUP:
  542.                     case CTRL_PGDN:
  543.                     case FWD:
  544.                     case BS:
  545.                     case CTRL_FWD:
  546.                     case CTRL_BS:
  547.                     case CTRL_HOME:
  548.                     case CTRL_END:
  549.                     case RUBOUT:
  550.                         if (!isMultiLine(wnd) && BlockMarked(wnd))    {
  551.                             ClearBlock(wnd);
  552.                             SendMessage(wnd, PAINT, 0, 0);
  553.                         }
  554.                         if (c != RUBOUT)
  555.                             break;
  556.                         if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
  557.                             break;
  558.                         Backward(wnd);
  559.                         currchar = CurrChar;
  560.                         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  561.                     case DEL:
  562.                         if (BlockMarked(wnd))    {
  563.                             SendMessage(wnd, COMMAND, ID_DELETETEXT, 0);
  564.                             return TRUE;
  565.                         }
  566.                         if (*(currchar+1) == '\0')
  567.                             return TRUE;
  568.                         if (*(currchar+1))    {
  569.                             int repaint = *currchar == '\n';
  570.                             strcpy(currchar, currchar+1);
  571.                             if (repaint)    {
  572.                                 BuildTextPointers(wnd);
  573.                                 SendMessage(wnd, PAINT, 0, 0);
  574.                             }
  575.                             else    {
  576.                                 AddTextPointers(wnd, wnd->CurrLine+1, -1);
  577.                                 WriteTextLine(wnd, NULL, wnd->WndRow+wnd->wtop, FALSE);
  578.                             }
  579.                         }
  580.                         wnd->TextChanged = TRUE;
  581.                         break;
  582.                     case INS:
  583.                         InvertCommandToggle(&MainMenu, ID_INSERT);
  584.                         SendMessage(NULLWND, SHOW_CURSOR, GetCommandToggle(&MainMenu, ID_INSERT), 0);
  585.                         break;
  586.                     case CTRL_FIVE:    /* same as Shift+Tab */
  587.                         if (!((int)p2 & (LEFTSHIFT | RIGHTSHIFT)))
  588.                             break;
  589.                     case UP:
  590.                     case DN:
  591.                         if (!isMultiLine(wnd))
  592.                             PostMessage(GetParent(wnd), msg, p1, p2);
  593.                         break;
  594.                     case '\t':
  595.                         if (!isMultiLine(wnd))
  596.                             PostMessage(GetParent(wnd), msg, p1, p2);
  597. #ifdef INCLUDE_MULTILINE
  598.                         else {
  599.                             int insmd = GetCommandToggle(&MainMenu, ID_INSERT);
  600.                             do  {
  601.                                 char *cc = CurrChar+1;
  602.                                 if (!insmd && *cc == '\0')
  603.                                     break;
  604.                                 SendMessage(wnd, KEYBOARD,
  605.                                     insmd ? ' ' : FWD, 0);
  606.                             } while (wnd->CurrCol % cfg.Tabs);
  607.                             return TRUE;
  608.                         }
  609. #endif
  610.                         break;
  611.                     case '\r':
  612.                         if (!isMultiLine(wnd))    {
  613.                             PostMessage(GetParent(wnd), msg, p1, p2);
  614.                             break;
  615.                         }
  616.                         c = '\n';
  617.                     default:
  618.                         if ((c != '\n' && c < ' ') || (c & 0x1000))
  619.                             /* ---- not recognized by editor --- */
  620.                             break;
  621. #ifdef INCLUDE_MULTILINE
  622.                         if (!isMultiLine(wnd) && BlockMarked(wnd))    {
  623.                             ResetEditBox(wnd);
  624.                             ClearBlock(wnd);
  625.                             currchar = CurrChar;
  626.                         }
  627. #endif
  628.                         if (*currchar == '\0')    {
  629.                             *currchar = '\n';
  630.                             *(currchar+1) = '\0';
  631.                             wnd->wlines++;
  632.                         }
  633.                         /* --- displayable char or newline --- */
  634.                         if (c == '\n' ||
  635.                                 GetCommandToggle(&MainMenu, ID_INSERT) ||
  636.                                     *currchar == '\n')    {
  637.                             if (wnd->text[wnd->textlen-1] != '\0')    {
  638.                                 wnd->textlen += GROWLENGTH;
  639.                                 wnd->text = realloc(wnd->text, wnd->textlen+1);
  640.                                 wnd->text[wnd->textlen-1] = '\0';
  641.                                 currchar = CurrChar;
  642.                             }
  643.                             /* ------ insert mode ------ */
  644.                             memmove(currchar+1, currchar, strlen(currchar)+1);
  645.                             AddTextPointers(wnd, wnd->CurrLine+1, 1);
  646. #ifdef INCLUDE_MULTILINE
  647.                             if (isMultiLine(wnd))
  648.                                 wnd->textwidth = max(wnd->textwidth,
  649.                                     (int) (TextLine(wnd, wnd->CurrLine+1)-
  650.                                     TextLine(wnd, wnd->CurrLine)));
  651.                             else
  652. #endif
  653.                                 wnd->textwidth = max(wnd->textwidth,
  654.                                     strlen(wnd->text));
  655.                             WriteTextLine(wnd, NULL,
  656.                                 wnd->wtop+wnd->WndRow, FALSE);
  657.                         }
  658.                         /* ----- put the char in the buffer ----- */
  659.                         *currchar = c;
  660.                         wnd->TextChanged = TRUE;
  661.                         if (c == '\n')    {
  662.                             wnd->wleft = 0;
  663.                             BuildTextPointers(wnd);
  664.                             End(wnd);
  665.                             Forward(wnd);
  666.                             SendMessage(wnd, PAINT, 0, 0);
  667.                             break;
  668.                         }
  669.                         /* ---------- test end of window --------- */
  670.                         if (WndCol == ClientWidth(wnd)-1)    {
  671.                             int dif;
  672.                             char *cp = currchar;
  673.                             while (*cp != ' ' && cp != TextLine(wnd, wnd->CurrLine))
  674.                                 --cp;
  675. #ifdef INCLUDE_MULTILINE
  676.                             if (!isMultiLine(wnd) || cp == TextLine(wnd, wnd->CurrLine) ||
  677.                                     !GetCommandToggle(&MainMenu, ID_WRAP))
  678. #endif
  679.                                 SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  680. #ifdef INCLUDE_MULTILINE
  681.                             else    {
  682.                                 dif = 0;
  683.                                 if (c != ' ')    {
  684.                                     dif = (int) (currchar - cp);
  685.                                     wnd->CurrCol -= dif;
  686.                                     SendMessage(wnd, KEYBOARD, DEL, 0);
  687.                                     --dif;
  688.                                 }
  689.                                 SendMessage(wnd, KEYBOARD, '\r', 0);
  690.                                 currchar = CurrChar;
  691.                                 wnd->CurrCol = dif;
  692.                                 if (c == ' ')
  693.                                     break;
  694.                             }
  695. #endif
  696.                         }
  697.                         /* ------ display the character ------ */
  698.                         SetStandardColor(wnd);
  699.                         PutWindowChar(wnd, WndCol+BorderAdj(wnd),
  700.                             wnd->WndRow+TopBorderAdj(wnd), c);
  701.                         /* ----- advance the pointers ------ */
  702.                         wnd->CurrCol++;
  703.                         break;
  704.                 }
  705.             }
  706.             SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  707.             return TRUE;
  708. #ifdef INCLUDE_MULTILINE
  709.         case COMMAND:    {
  710.             char *bbl, *bel, *bb;
  711.             int len;
  712.  
  713.             if (BlockMarked(wnd))    {
  714.                 bbl = TextLine(wnd, wnd->BlkBegLine) + wnd->BlkBegCol;
  715.                 bel = TextLine(wnd, wnd->BlkEndLine) + wnd->BlkEndCol;
  716.                 len = (int) (bel - bbl);
  717.             }
  718.             switch ((int)p1)    {
  719. #ifdef INCLUDE_CLIPBOARD
  720.                 case ID_CUT:
  721.                 case ID_COPY:
  722.                     ClipboardLength = len;
  723.                     Clipboard = realloc(Clipboard, ClipboardLength);
  724.                     if (Clipboard != NULL)
  725.                         memmove(Clipboard, bbl, ClipboardLength);
  726. #endif
  727.                 case ID_DELETETEXT:
  728.                     if (p1 != ID_COPY)    {
  729.                         if (p1 != ID_CUT)
  730.                             SaveDeletedText(wnd, bbl, len);
  731.                         wnd->TextChanged = TRUE;
  732.                         strcpy(bbl, bel);
  733.                         wnd->CurrLine = TextLineNumber(wnd, bbl - wnd->BlkBegCol);
  734.                         wnd->CurrCol = wnd->BlkBegCol;
  735.                         wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
  736.                         if (wnd->WndRow < 0)    {
  737.                             wnd->wtop = wnd->BlkBegLine;
  738.                             wnd->WndRow = 0;
  739.                         }
  740.                         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  741.                     }
  742.                     ClearBlock(wnd);
  743.                     BuildTextPointers(wnd);
  744.                     SendMessage(wnd, PAINT, 0, 0);
  745.                     return TRUE;
  746. #ifdef INCLUDE_CLIPBOARD
  747.                 case ID_CLEAR:
  748.                     SaveDeletedText(wnd, bbl, len);
  749.                     wnd->CurrLine = TextLineNumber(wnd, bbl);
  750.                     wnd->CurrCol = wnd->BlkBegCol;
  751.                     wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
  752.                     if (wnd->WndRow < 0)    {
  753.                         wnd->WndRow = 0;
  754.                         wnd->wtop = wnd->BlkBegLine;
  755.                     }
  756.                     while (bbl < bel)    {
  757.                         char *cp = strchr(bbl, '\n');
  758.                         if (cp > bel)
  759.                             cp = bel;
  760.                         strcpy(bbl, cp);
  761.                         bel -= (int) (cp - bbl);
  762.                         bbl++;
  763.                     }
  764.                     ClearBlock(wnd);
  765.                     BuildTextPointers(wnd);
  766.                     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  767.                     SendMessage(wnd, PAINT, 0, 0);
  768.                     wnd->TextChanged = TRUE;
  769.                     return TRUE;
  770.                 case ID_PASTE:
  771.                     if (Clipboard != NULL)    {
  772.                         PasteText(wnd, Clipboard, ClipboardLength);
  773.                         wnd->TextChanged = TRUE;
  774.                     }
  775.                     return TRUE;
  776. #endif
  777.                 case ID_UNDO:
  778.                     if (wnd->DeletedText != NULL)    {
  779.                         PasteText(wnd, wnd->DeletedText, wnd->DeletedLength);
  780.                         free(wnd->DeletedText);
  781.                         wnd->DeletedText = NULL;
  782.                     }
  783.                     return TRUE;
  784.                 case ID_PARAGRAPH:    {
  785.                     char *bl;
  786.                     int bc, ec;
  787.                     int fl, el;
  788.                     int Blocked;
  789.  
  790.                     el = wnd->BlkEndLine;
  791.                     ec = wnd->BlkEndCol;
  792.                     if (!BlockMarked(wnd))    {
  793.                         Blocked = FALSE;
  794.                         /* ---- forming paragraph from cursor position --- */
  795.                         fl = wnd->wtop + wnd->WndRow;
  796.                         bl = TextLine(wnd, wnd->CurrLine);
  797.                         bc = wnd->CurrCol;
  798.                         Home(wnd);
  799.                         bbl = bel = bl;
  800.                         if (bc >= ClientWidth(wnd))
  801.                             bc = 0;
  802.                         /* ---- locate the end of the paragraph ---- */
  803.                         while (*bel)    {
  804.                             int blank = TRUE;
  805.                             char *bll = bel;
  806.                             /* --- blank line marks end of paragraph --- */
  807.                             while (*bel && *bel != '\n')    {
  808.                                 if (*bel != ' ')
  809.                                     blank = FALSE;
  810.                                 bel++;
  811.                             }
  812.                             if (blank)    {
  813.                                 bel = bll;
  814.                                 break;
  815.                             }
  816.                             if (*bel)
  817.                                 bel++;
  818.                         }
  819.                         if (bel == bbl)    {
  820.                             SendMessage(wnd, KEYBOARD, DN, 0);
  821.                             return TRUE;
  822.                         }
  823.                         if (*bel == '\0')
  824.                             --bel;
  825.                         if (*bel == '\n')
  826.                             --bel;
  827.                     }
  828.                     else    {
  829.                         Blocked = TRUE;
  830.                         /* ---- forming paragraph from marked block --- */
  831.                         fl = wnd->BlkBegLine;
  832.                         bc = wnd->CurrCol = wnd->BlkBegCol;
  833.                         wnd->CurrLine = fl;
  834.                         if (fl < wnd->wtop)
  835.                             wnd->wtop = fl;
  836.                         wnd->WndRow = fl - wnd->wtop;
  837.                         SendMessage(wnd, KEYBOARD, '\r', 0);
  838.                         el++, fl++;
  839.                         if (bc != 0)    {
  840.                             SendMessage(wnd, KEYBOARD, '\r', 0);
  841.                             el++, fl ++;
  842.                         }
  843.                         bc = 0;
  844.                         bl = TextLine(wnd, fl);
  845.                         wnd->CurrLine = fl;
  846.                         bbl = bl + bc;
  847.                         bel = TextLine(wnd, el) + ec;
  848.                     }
  849.  
  850.                     /* --- change all newlines in block to spaces --- */
  851.                     while (CurrChar < bel)    {
  852.                         if (*CurrChar == '\n')    {
  853.                             *CurrChar = ' ';
  854.                             wnd->CurrLine++;
  855.                             wnd->CurrCol = 0;
  856.                         }
  857.                         else
  858.                             wnd->CurrCol++;
  859.                     }
  860.  
  861.                     /* ---- insert newlines at new margin boundaries ---- */
  862.                     bb = bbl;
  863.                     while (bbl < bel)    {
  864.                         bbl++;
  865.                         if ((int)(bbl - bb) == ClientWidth(wnd)-1)    {
  866.                             while (*bbl != ' ' && bbl > bb)
  867.                                 --bbl;
  868.                             if (*bbl != ' ')    {
  869.                                 bbl = strchr(bbl, ' ');
  870.                                 if (bbl == NULL || bbl >= bel)
  871.                                     break;
  872.                             }
  873.                             *bbl = '\n';
  874.                             bb = bbl+1;
  875.                         }
  876.                     }
  877.                     ec = (int)(bel - bb);
  878.                     BuildTextPointers(wnd);
  879.  
  880.                     if (Blocked)    {
  881.                         /* ---- position cursor at end of new paragraph ---- */
  882.                         if (el < wnd->wtop ||
  883.                                 wnd->wtop + ClientHeight(wnd) < el)
  884.                             wnd->wtop = el-ClientHeight(wnd);
  885.                         if (wnd->wtop < 0)
  886.                             wnd->wtop = 0;
  887.                         wnd->WndRow = el - wnd->wtop;
  888.                         wnd->CurrLine = el;
  889.                         wnd->CurrCol = ec;
  890.                         SendMessage(wnd, KEYBOARD, '\r', 0);
  891.                         SendMessage(wnd, KEYBOARD, '\r', 0);
  892.                     }
  893.                     else    {
  894.                         /* --- put cursor back at beginning --- */
  895.                         wnd->CurrLine = TextLineNumber(wnd, bl);
  896.                         wnd->CurrCol = bc;
  897.                         if (fl < wnd->wtop)
  898.                             wnd->wtop = fl;
  899.                         wnd->WndRow = fl - wnd->wtop;
  900.                     }
  901.                     SendMessage(wnd, PAINT, 0, 0);
  902.                     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  903.                     wnd->TextChanged = TRUE;
  904.                     BuildTextPointers(wnd);
  905.                     return TRUE;
  906.                 }
  907. #ifdef INCLUDE_DIALOG_BOXES
  908.                 case ID_SEARCH:
  909.                     SearchTextBox(wnd);
  910.                     break;
  911.                 case ID_REPLACE:
  912.                     ReplaceTextBox(wnd);
  913.                     break;
  914.                 case ID_SEARCHNEXT:
  915.                     SearchNext(wnd, TRUE);
  916.                     break;
  917. #endif
  918.                 default:
  919.                     break;
  920.             }
  921.             break;
  922.         }
  923. #endif
  924.         case CLOSE_WINDOW:
  925.             SendMessage(NULLWND, HIDE_CURSOR, 0, 0);
  926.             if (wnd->DeletedText != NULL)
  927.                 free(wnd->DeletedText);
  928.             break;
  929.         default:
  930.             break;
  931.     }
  932.     return BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  933. }
  934.  
  935. #ifdef INCLUDE_MULTILINE
  936. static void PasteText(WINDOW wnd, char *SaveTo, int len)
  937. {
  938.     int plen = strlen(wnd->text) + len;
  939.     char *bl, *el;
  940.  
  941.     if (plen > wnd->textlen)    {
  942.         wnd->text = realloc(wnd->text, plen+1);
  943.         wnd->textlen = plen;
  944.     }
  945.     bl = CurrChar;
  946.     el = bl+len;
  947.     memmove(el,    bl,    strlen(bl)+1);
  948.     memmove(bl, SaveTo, len);
  949.     BuildTextPointers(wnd);
  950.     SendMessage(wnd, PAINT, 0, 0);
  951. }
  952.  
  953. static void SaveDeletedText(WINDOW wnd, char *bbl, int len)
  954. {
  955.     wnd->DeletedLength = len;
  956.     if ((wnd->DeletedText = realloc(wnd->DeletedText, len)) != NULL)
  957.         memmove(wnd->DeletedText, bbl, len);
  958. }
  959.  
  960. #endif
  961.  
  962. static void Forward(WINDOW wnd)
  963. {
  964.     char *cc = CurrChar+1;
  965.     if (*cc == '\0')
  966.         return;
  967. #ifdef INCLUDE_MULTILINE
  968.     if (*CurrChar == '\n')    {
  969.         Home(wnd);
  970.         Downward(wnd);
  971.     }
  972. #endif
  973.     else    {
  974.         wnd->CurrCol++;
  975.         if (WndCol == ClientWidth(wnd))    {
  976.             wnd->wleft++;
  977.             SendMessage(wnd, PAINT, 0, 0);
  978.         }
  979.     }
  980. }
  981.  
  982. static void StickEnd(WINDOW wnd)
  983. {
  984.     char *cp = TextLine(wnd, wnd->CurrLine);
  985.     char *cp1 = strchr(cp, '\n');
  986.     int len = 0;
  987.  
  988.     if (cp1 != NULL)
  989.         len = (int) (cp1 - cp);
  990.     wnd->CurrCol = min(len, wnd->CurrCol);
  991.     if (wnd->wleft > wnd->CurrCol)    {
  992.         wnd->wleft = max(0, wnd->CurrCol - 4);
  993.         SendMessage(wnd, PAINT, 0, 0);
  994.     }
  995.     else if (wnd->CurrCol-wnd->wleft >= ClientWidth(wnd))    {
  996.         wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
  997.         SendMessage(wnd, PAINT, 0, 0);
  998.     }
  999. }
  1000.  
  1001. #ifdef INCLUDE_MULTILINE
  1002. static void Downward(WINDOW wnd)
  1003. {
  1004.     if (isMultiLine(wnd) && wnd->WndRow+wnd->wtop+1 < wnd->wlines)    {
  1005.         DownLine(wnd);
  1006.         if (wnd->WndRow == ClientHeight(wnd)-1)
  1007.             SendMessage(wnd, SCROLL, TRUE, 0);
  1008.         wnd->WndRow++;
  1009.         StickEnd(wnd);
  1010.     }
  1011. }
  1012.  
  1013. static void DownLine(WINDOW wnd)
  1014. {
  1015.     wnd->CurrLine++;
  1016. }
  1017.  
  1018. static void UpLine(WINDOW wnd)
  1019. {
  1020.     if (wnd->CurrLine > 0)
  1021.         --wnd->CurrLine;
  1022. }
  1023.  
  1024. static void Upward(WINDOW wnd)
  1025. {
  1026.     if (isMultiLine(wnd) && wnd->CurrLine != 0)    {
  1027.         UpLine(wnd);
  1028.         if (wnd->WndRow == 0)
  1029.             SendMessage(wnd, SCROLL, FALSE, 0);
  1030.         --wnd->WndRow;
  1031.         StickEnd(wnd);
  1032.     }
  1033. }
  1034. #endif
  1035.  
  1036. static void Backward(WINDOW wnd)
  1037. {
  1038.     if (wnd->CurrCol)    {
  1039.         if (wnd->CurrCol-- <= wnd->wleft)    {
  1040.             if (wnd->wleft != 0)    {
  1041.                 --wnd->wleft;
  1042.                 SendMessage(wnd, PAINT, 0, 0);
  1043.                 return;
  1044.             }
  1045.         }
  1046.         else
  1047.             return ;
  1048.     }
  1049. #ifdef INCLUDE_MULTILINE
  1050.     if (isMultiLine(wnd) && wnd->CurrLine != 0)    {
  1051.         Upward(wnd);
  1052.         End(wnd);
  1053.     }
  1054. #endif
  1055. }
  1056.  
  1057. static void End(WINDOW wnd)
  1058. {
  1059.     while (*CurrChar && *CurrChar != '\n')
  1060.         ++wnd->CurrCol;
  1061.     if (WndCol >= ClientWidth(wnd))    {
  1062.         wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
  1063.         SendMessage(wnd, PAINT, 0, 0);
  1064.     }
  1065. }
  1066.  
  1067. static void Home(WINDOW wnd)
  1068. {
  1069.     wnd->CurrCol = 0;
  1070.     if (wnd->wleft != 0)    {
  1071.         wnd->wleft = 0;
  1072.         SendMessage(wnd, PAINT, 0, 0);
  1073.     }
  1074. }
  1075.  
  1076. #define isWhite(c)     ((c) == ' ' || (c) == '\n')
  1077.  
  1078. static void NextWord(WINDOW wnd)
  1079. {
  1080.     int savetop = wnd->wtop;
  1081.     int saveleft = wnd->wleft;
  1082.     ClearAttribute(wnd, VISIBLE);
  1083.     while (!isWhite(*CurrChar))    {
  1084.         char *cc = CurrChar+1;
  1085.         if (*cc == '\0')
  1086.             break;
  1087.         Forward(wnd);
  1088.     }
  1089.     while (isWhite(*CurrChar))    {
  1090.         char *cc = CurrChar+1;
  1091.         if (*cc == '\0')
  1092.             break;
  1093.         Forward(wnd);
  1094.     }
  1095.     AddAttribute(wnd, VISIBLE);
  1096.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1097.     if (wnd->wtop != savetop || wnd->wleft != saveleft)
  1098.         SendMessage(wnd, PAINT, 0, 0);
  1099. }
  1100.  
  1101. static void PrevWord(WINDOW wnd)
  1102. {
  1103.     int savetop = wnd->wtop;
  1104.     int saveleft = wnd->wleft;
  1105.     ClearAttribute(wnd, VISIBLE);
  1106.     Backward(wnd);
  1107.     while (isWhite(*CurrChar))    {
  1108.         if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
  1109.             break;
  1110.         Backward(wnd);
  1111.     }
  1112.     while (!isWhite(*CurrChar))    {
  1113.         if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
  1114.             break;
  1115.         Backward(wnd);
  1116.     }
  1117.     if (isWhite(*CurrChar))
  1118.         Forward(wnd);
  1119.     AddAttribute(wnd, VISIBLE);
  1120.     if (wnd->wleft != saveleft)
  1121.         if (wnd->CurrCol >= saveleft)
  1122.             if (wnd->CurrCol - saveleft < ClientWidth(wnd))
  1123.                 wnd->wleft = saveleft;
  1124.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1125.     if (wnd->wtop != savetop || wnd->wleft != saveleft)
  1126.         SendMessage(wnd, PAINT, 0, 0);
  1127. }
  1128.  
  1129. static void ResetEditBox(WINDOW wnd)
  1130. {
  1131.     *wnd->text = '\0';
  1132.     wnd->wlines = 0;
  1133.     wnd->CurrLine = 0;
  1134.     wnd->CurrCol = 0;
  1135.     wnd->WndRow = 0;
  1136.     wnd->TextChanged = FALSE;
  1137.     wnd->wleft = 0;
  1138.     wnd->textwidth = 0;
  1139. }
  1140.  
  1141. static void AddTextPointers(WINDOW wnd, int lineno, int ct)
  1142. {
  1143.     while (lineno < wnd->wlines)
  1144.         *((wnd->TextPointers) + lineno++) += ct;
  1145. }
  1146.  
  1147. static int TextLineNumber(WINDOW wnd, char *lp)
  1148. {
  1149.     int lineno;
  1150.     char *cp;
  1151.     for (lineno = 0; lineno < wnd->wlines; lineno++)    {
  1152.         cp = wnd->text + *((wnd->TextPointers) + lineno);
  1153.         if (cp == lp)
  1154.             return lineno;
  1155.         if (lineno && cp > lp)
  1156.             return lineno - 1;
  1157.     }
  1158.     return 0;
  1159. }
  1160.  
  1161. #ifdef INCLUDE_MULTILINE
  1162. #ifdef INCLUDE_DIALOG_BOXES
  1163.  
  1164. extern DBOX SearchText;
  1165. extern DBOX ReplaceText;
  1166. static int checkcase = TRUE;
  1167. static int Replacing = FALSE;
  1168.  
  1169. static void ReplaceTextBox(WINDOW wnd)
  1170. {
  1171.     if (checkcase)
  1172.         SetCheckBox(&ReplaceText, ID_MATCHCASE);
  1173.     if (DialogBox(wnd, &ReplaceText, TRUE, NULL))    {
  1174.         checkcase = CheckBoxSetting(&ReplaceText, ID_MATCHCASE);
  1175.         Replacing = TRUE;
  1176.         SearchNext(wnd, FALSE);
  1177.     }
  1178. }
  1179.  
  1180. static void SearchTextBox(WINDOW wnd)
  1181. {
  1182.     if (checkcase)
  1183.         SetCheckBox(&SearchText, ID_MATCHCASE);
  1184.     if (DialogBox(wnd, &SearchText, TRUE, NULL))    {
  1185.         checkcase = CheckBoxSetting(&SearchText, ID_MATCHCASE);
  1186.         Replacing = FALSE;
  1187.         SearchNext(wnd, FALSE);
  1188.     }
  1189. }
  1190.  
  1191. static int SearchCmp(int a, int b)
  1192. {
  1193.     if (b == '\n')
  1194.         b = ' ';
  1195.     if (checkcase)
  1196.         return a != b;
  1197.     return tolower(a) != tolower(b);
  1198. }
  1199.  
  1200. static void SearchNext(WINDOW wnd, int incr)
  1201. {
  1202.     char *s1, *s2, *cp1 = CurrChar;
  1203.     DBOX *db = Replacing ? &ReplaceText : &SearchText;
  1204.     char *cp = GetEditBoxText(db, ID_SEARCHFOR);
  1205.     int rpl = TRUE, FoundOne = FALSE;
  1206.     while (rpl)    {
  1207.         rpl = Replacing ?
  1208.                 CheckBoxSetting(&ReplaceText, ID_REPLACEALL) : FALSE;
  1209.         if (BlockMarked(wnd))    {
  1210.             ClearBlock(wnd);
  1211.             SendMessage(wnd, PAINT, 0, 0);
  1212.         }
  1213.         if (cp && cp1 && *cp && *cp1)    {
  1214.             if (incr)
  1215.                 cp1++;
  1216.             while (*cp1)    {
  1217.                 s1 = cp;
  1218.                 s2 = cp1;
  1219.                 while (*s1 && *s1 != '\n')    {
  1220.                     if (SearchCmp(*s1,*s2))
  1221.                         break;
  1222.                     s1++, s2++;
  1223.                 }
  1224.                 if (*s1 == '\0' || *s1 == '\n')
  1225.                     break;
  1226.                 cp1++;
  1227.             }
  1228.             if (*s1 == 0 || *s1 == '\n')    {
  1229.                 /* ----- hit at *cp1 ------- */
  1230.                 FoundOne = TRUE;
  1231.                 wnd->BlkEndLine = TextLineNumber(wnd, s2);
  1232.                 wnd->BlkEndCol = (int)(s2 - TextLine(wnd, wnd->BlkEndLine));
  1233.  
  1234.                 wnd->BlkBegLine = TextLineNumber(wnd, cp1);
  1235.                 wnd->BlkBegCol = (int)(cp1 - TextLine(wnd, wnd->BlkBegLine));
  1236.  
  1237.                 wnd->CurrCol = wnd->BlkBegCol;
  1238.                 wnd->CurrLine = wnd->BlkBegLine;
  1239.                 wnd->WndRow = wnd->CurrLine - wnd->wtop;
  1240.  
  1241.                 if (WndCol > ClientWidth(wnd)-1)
  1242.                     wnd->wleft = wnd->CurrCol;
  1243.                 if (wnd->WndRow > ClientHeight(wnd)-1)    {
  1244.                     wnd->wtop = wnd->CurrLine;
  1245.                     wnd->WndRow = 0;
  1246.                 }
  1247.                 SendMessage(wnd, PAINT, 0, 0);
  1248.                 PostMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1249.                 if (Replacing)    {
  1250.                     if (rpl || YesNoBox("Replace the text?"))    {
  1251.                         char *cr = GetEditBoxText(db, ID_REPLACEWITH);
  1252.                         int oldlen = strlen(cp)-1;
  1253.                         int newlen = strlen(cr)-1;
  1254.                         int dif;
  1255.                         if (oldlen < newlen)    {
  1256.                             dif = newlen-oldlen;
  1257.                             if (wnd->textlen < strlen(wnd->text)+dif)    {
  1258.                                 int offset = (int)(cp1-wnd->text);
  1259.                                 wnd->textlen += dif;
  1260.                                 wnd->text = realloc(wnd->text, wnd->textlen);
  1261.                                 if (wnd->text == NULL)
  1262.                                     return;
  1263.                                 cp1 = wnd->text + offset;
  1264.                             }
  1265.                             memmove(cp1+dif, cp1, strlen(cp1)+1);
  1266.                         }
  1267.                         else if (oldlen > newlen)    {
  1268.                             dif = oldlen-newlen;
  1269.                             memmove(cp1, cp1+dif, strlen(cp1)+1);
  1270.                         }
  1271.                         strncpy(cp1, cr, newlen);
  1272.                         wnd->TextChanged = TRUE;
  1273.                         BuildTextPointers(wnd);
  1274.                     }
  1275.                     if (rpl)    {
  1276.                         incr = TRUE;
  1277.                         continue;
  1278.                     }
  1279.                     ClearBlock(wnd);
  1280.                     SendMessage(wnd, PAINT, 0, 0);
  1281.                 }
  1282.                 return;
  1283.             }
  1284.             break;
  1285.         }
  1286.     }
  1287.     if (cp && *cp && !FoundOne)
  1288.         MessageBox("Search/Replace Text", "No match found");
  1289. }
  1290.  
  1291. #endif
  1292. #endif
  1293.